package com.qqbot.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.Map.Entry;

public class HttpUtil {
    private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);
    /**
     * setConnectionRequestTimeout(timeOut) // 设置从连接池获取到连接的超时时间
     * setConnectTimeout(timeOut) // 设置HTTP连接超时时间
     * setSocketTimeout(timeOut) // 设置Socket超时时间，等待响应超时（读取数据超时）
     */
    private static final int SOCKET_TIMEOUT_IN_MILLIS = Integer.parseInt("300000");

    private static final RequestConfig requestConfig = RequestConfig.custom()
            .setConnectionRequestTimeout(SOCKET_TIMEOUT_IN_MILLIS)
            .setConnectTimeout(SOCKET_TIMEOUT_IN_MILLIS)
            .setSocketTimeout(SOCKET_TIMEOUT_IN_MILLIS)
            .build();

    private static final CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();

    public static String httpGet(String url) {
        HttpGet httpget = new HttpGet(url);
        String result = "";
        try {
            CloseableHttpResponse response = httpClient.execute(httpget);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
                EntityUtils.consume(entity);
            }
        } catch (IOException e) {
            logger.error("Failed to do http get request.", e.getMessage());
        }
        return result;
    }

    /**
     * 获取请求结果流
     *
     * @param url 请求url
     * @return 结果输入流
     */
    public static InputStream get(String url) {
        HttpGet httpget = new HttpGet(url);
        try {
            CloseableHttpResponse response = httpClient.execute(httpget);
            HttpEntity entity = response.getEntity();
            if (entity != null && entity.isStreaming()) {
                return entity.getContent();
            }
        } catch (IOException e) {
            logger.error("Failed to httpGet input stream.", e.getMessage());
        }
        return null;
    }

    public static String httpGet(String url, Map<String, String> headers) {
        HttpGet httpget = new HttpGet(url);
        if (headers != null) {
            Set<String> keys = headers.keySet();
            for (Iterator<String> i = keys.iterator(); i.hasNext(); ) {
                String key = (String) i.next();
                httpget.addHeader(key, headers.get(key));
            }
        }
        String result = "";
        try {
            CloseableHttpResponse response = httpClient.execute(httpget);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
                EntityUtils.consume(entity);
            }
        } catch (Exception e) {
            logger.error("Exception happened when do httpGet", e.getMessage());
        }
        return result;
    }

    public static String httpPost(String url, Map<String, String> params) {
        HttpPost httppost = new HttpPost(url);
        List<NameValuePair> param = new ArrayList<>();
        Iterator<Entry<String, String>> iter = params.entrySet().iterator();
        while (iter.hasNext()) {
            Entry<String, String> entry = iter.next();
            String key = entry.getKey();
            String val = entry.getValue();
            param.add(new BasicNameValuePair(key, val));
        }
        String result = "";
        try {
            UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(param, "UTF-8");
            httppost.setEntity(uefEntity);
            CloseableHttpResponse response = httpClient.execute(httppost);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
                EntityUtils.consume(entity);
            }
        } catch (IOException e) {
            logger.error("Failed to httpGet input stream.", e.getMessage());
        }
        return result;
    }

    public static String httpPost(String url, Map<String, String> params, Map<String, String> headers) {
        HttpPost httppost = new HttpPost(url);
        if (headers != null) {
            Set<String> keys = headers.keySet();
            for (Iterator<String> i = keys.iterator(); i.hasNext(); ) {
                String key = (String) i.next();
                httppost.addHeader(key, headers.get(key));
            }
        }
        List<NameValuePair> param = new ArrayList<>();
        Iterator<Entry<String, String>> iter = params.entrySet().iterator();
        while (iter.hasNext()) {
            Entry<String, String> entry = iter.next();
            String key = entry.getKey();
            String val = entry.getValue();
            param.add(new BasicNameValuePair(key, val));
        }
        String result = "";
        try {
            UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(param, "UTF-8");
            httppost.setEntity(uefEntity);
            CloseableHttpResponse response = httpClient.execute(httppost);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
                EntityUtils.consume(entity);
            }
        } catch (IOException e) {
            logger.error("Failed to httpGet input stream.", e.getMessage());
        }
        return result;
    }

    public static String httpPost(String url, JSONObject params, Map<String, String> headers) {
        HttpPost httppost = new HttpPost(url);
        if (headers != null) {
            Set<String> keys = headers.keySet();
            for (Iterator<String> i = keys.iterator(); i.hasNext(); ) {
                String key = (String) i.next();
                httppost.addHeader(key, headers.get(key));
            }
        }
        String result = "";
        try {
            StringEntity postEntity = new StringEntity(params.toJSONString(), ContentType.APPLICATION_JSON);
            httppost.setEntity(postEntity);
            CloseableHttpResponse response = httpClient.execute(httppost);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
                EntityUtils.consume(entity);
            }
        } catch (IOException e) {
            logger.error("Failed to httpGet input stream.", e.getMessage());
        }
        return result;
    }

    public static InputStream fileHttpPost(String url, JSONObject params) {
        HttpPost httppost = new HttpPost(url);
        try {
            StringEntity postEntity = new StringEntity(params.toJSONString(), ContentType.APPLICATION_JSON);
            httppost.setEntity(postEntity);
            CloseableHttpResponse response = httpClient.execute(httppost);
            HttpEntity entity = response.getEntity();
            if (entity != null && entity.isStreaming()) {
                return entity.getContent();
            }
        } catch (IOException e) {
            logger.error("Failed to httpGet input stream.", e.getMessage());
        }
        return null;
    }

    public static HttpEntity fileHttpPost(String url, Map<String, String> headers, JSONObject params) {
        HttpPost httppost = new HttpPost(url);
        if (Objects.nonNull(headers)) {
            Set<String> keys = headers.keySet();
            for (Iterator<String> i = keys.iterator(); i.hasNext(); ) {
                String key = i.next();
                httppost.addHeader(key, headers.get(key));
            }
        }
        try {
            StringEntity postEntity = new StringEntity(params.toJSONString(), ContentType.APPLICATION_JSON);
            httppost.setEntity(postEntity);
            CloseableHttpResponse response = httpClient.execute(httppost);
            HttpEntity entity = response.getEntity();
            if (entity != null && entity.isStreaming()) {
                return entity;
            }
        } catch (IOException e) {
            logger.error("Failed to httpGet input stream.", e.getMessage());
        }
        return null;
    }

    /**
     * 根据ContentType的POST请求
     *
     * @param url         请求url
     * @param headers     请求头
     * @param params      请求参数
     * @param contentType 请求类型
     * @return
     */
    public static String httpPostByContentType(String url, Map<String, String> headers, String params, ContentType contentType) {
        HttpPost httpPost = new HttpPost(url);
        if (headers != null) {
            Set<String> keys = headers.keySet();
            for (Iterator<String> i = keys.iterator(); i.hasNext(); ) {
                String key = (String) i.next();
                httpPost.addHeader(key, headers.get(key));
            }
        }
        StringEntity postEntity = new StringEntity(params, contentType);
        httpPost.setEntity(postEntity);
        String result = null;
        try {
            CloseableHttpResponse response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
                EntityUtils.consume(entity);
            }
        } catch (IOException e) {
            logger.error("Failed to httpPost input stream.", e.getMessage());
        }
        return result;
    }

    /**
     * 发起httpPost请求，body请求参数为：json字符串
     *
     * @param url
     * @param bodyJsonStr
     * @return
     */
    public static String httpPost(String url, String bodyJsonStr, Map<String, String> headers) {
        HttpPost post = new HttpPost(url);
        String result = "";
        if (headers != null) {
            Set<String> keys = headers.keySet();
            for (Iterator<String> i = keys.iterator(); i.hasNext(); ) {
                String key = i.next();
                post.addHeader(key, headers.get(key));
            }
        }
        try {
            StringEntity postEntity = new StringEntity(bodyJsonStr, ContentType.APPLICATION_JSON);
            post.setEntity(postEntity);
            CloseableHttpResponse response = httpClient.execute(post);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
                EntityUtils.consume(entity);
            }
        } catch (IOException e) {
            logger.error("Failed to httpPost=========>>>>>>>>error:{}", e.getMessage());
        }
        return result;
    }

}
